package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huiminpay.common.cache.Cache;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.util.RedisUtil;
import com.huiminpay.common.cache.util.StringUtil;
import com.huiminpay.transaction.api.dto.PayChannelDTO;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PlatformChannelDTO;
import com.huiminpay.transaction.api.service.PayChannelService;
import com.huiminpay.transaction.convert.PayChannelParamConvert;
import com.huiminpay.transaction.convert.PlatformChannelConvert;
import com.huiminpay.transaction.entity.AppPlatformChannel;
import com.huiminpay.transaction.entity.PayChannelParam;
import com.huiminpay.transaction.entity.PlatformChannel;
import com.huiminpay.transaction.mapper.AppPlatformChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelParamMapper;
import com.huiminpay.transaction.mapper.PlatformChannelMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;

import javax.annotation.Resource;
import java.util.List;

@Service
@Slf4j
public class PayChannelServiceImpl implements PayChannelService {

    /**
     * \* 获取平台服务类型
     * \* @return
     */
    @Resource
    private PlatformChannelMapper platformChannelMapper;

    @Resource
    private AppPlatformChannelMapper appPlatformChannelMapper;

    @Resource
    private PayChannelParamMapper payChannelParamMapper;

    @Resource
    private Cache cache;

    @Override
    public List<PlatformChannelDTO> queryPlatformChannel() throws BusinessException {
        List<PlatformChannel> platformChannels = platformChannelMapper.selectList(null);
        List<PlatformChannelDTO> platformChannelDTOS = PlatformChannelConvert.INSTANCE.listentity2listdto(platformChannels);

        return platformChannelDTOS;
    }

    /**
     * \* 为app绑定平台服务类型
     * \* @param appId 应用id
     * \* @param platformChannelCodes 平台服务类型列表
     * @param appId
     * @param platformChannelCodes
     */
    @Override
    public void bindPlatformChannelForApp(String appId, String platformChannelCodes) throws BusinessException {
        // 根据appId和平台服务类型code查询app_platform_channel
        QueryWrapper<AppPlatformChannel> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(AppPlatformChannel::getAppId, appId).eq(AppPlatformChannel::getPlatformChannel, platformChannelCodes);
        AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(wrapper);
        // 如果没有绑定则绑定
        if (appPlatformChannel == null) {
            appPlatformChannel = new AppPlatformChannel();
            appPlatformChannel.setAppId(appId);
            appPlatformChannel.setPlatformChannel(platformChannelCodes);
            appPlatformChannelMapper.insert(appPlatformChannel);
        } else {
            throw new BusinessException(CommonErrorCode.E_200018);
        }
    }

    /**
     * \* 应用是否已经绑定了某个服务类型
     * \* @param appId
     * \* @param platformChannel
     * \* @return 已绑定返回1，否则 返回0
     * @param appId
     * @param platformChannel
     */
    @Override
    public int queryAppBindPlatformChannel(String appId, String platformChannel) throws BusinessException {
        QueryWrapper<AppPlatformChannel> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(AppPlatformChannel::getAppId, appId).eq(AppPlatformChannel::getPlatformChannel, platformChannel);
        Integer count = appPlatformChannelMapper.selectCount(wrapper);
        if (count > 0) {
            return 1;
        } else {
            return 0;
        }

    }

    /**
     * \* 根据平台服务类型获取支付渠道列表
     * \* @param platformChannelCode
     * \* @return
     * @param platformChannelCode
     */
    @Override
    public List<PayChannelDTO> queryPayChannelByPlatformChannel(String platformChannelCode) throws BusinessException {

        return platformChannelMapper.selectPayChannelByPlatformChannel(platformChannelCode);
    }

    /**
     * /* 保存支付渠道参数
     * /* @param payChannelParam 商户原始支付渠道参数
     * @param payChannelParam
     */
    @Override
    public void savePayChannelParam(PayChannelParamDTO payChannelParam) throws BusinessException {
        // 校验
        if (payChannelParam == null ||
                StringUtil.isBlank(payChannelParam.getAppId()) ||
                StringUtil.isBlank(payChannelParam.getPlatformChannelCode()) ||
                StringUtil.isBlank(payChannelParam.getPayChannel())) {
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        // 1.2根据appid和服务类型   查询应用与服务类型绑定id
        Long appPlatformChannelId = selectIdByAppPlatformChannel(payChannelParam.getAppId(), payChannelParam.getPlatformChannelCode());
        // 校验若appPlatformChannelId为null，抛出异常
        // 应用未绑定该服务类型不可进行支付渠道参数配置
        if (appPlatformChannelId == null) {
            throw new BusinessException(CommonErrorCode.E_300010);
        }
        // 3.根据应用与服务类型绑定id  和  支付渠道查询参数信息
        LambdaQueryWrapper<PayChannelParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PayChannelParam::getAppPlatformChannelId, appPlatformChannelId).eq(PayChannelParam::getPayChannel, payChannelParam.getPayChannel());
        PayChannelParam payChannelParam1 = payChannelParamMapper.selectOne(wrapper);
        // 更新已有配置
        if (payChannelParam1 != null) {
            payChannelParam1.setChannelName(payChannelParam.getChannelName());
            payChannelParam1.setParam(payChannelParam.getParam());

            payChannelParamMapper.updateById(payChannelParam1);
        } else {
            // 添加新配置
            PayChannelParam entity = PayChannelParamConvert.INSTANCE.dto2entity(payChannelParam);
            entity.setId(null);
            // 应用与服务类型绑定id
            entity.setAppPlatformChannelId(appPlatformChannelId);
            payChannelParamMapper.insert(entity);
        }
        updateCache(payChannelParam.getAppId(), payChannelParam.getPlatformChannelCode());


    }

    private void updateCache(String appId, String platformChannel) {
        // 处理redis缓存
        // 1.key的构建 如：HM_PAY_PARAM:b910da455bc84514b324656e1088320b:huimin_c2b
        String redisKey = RedisUtil.keyBuilder(appId, platformChannel);
        // 查询redis查询key是否存在
        Boolean exists = cache.exists(redisKey);
        // 若存在，则清除
        if (exists) {
            cache.del(redisKey);
        }
        // 3.从数据库查询应用的服务类型对应的实际支付参数，并重新存入缓存
        List<PayChannelParamDTO> payChannelParamDTOS = queryPayChannelParamByAppAndPlatform(appId, platformChannel);
        if (payChannelParamDTOS != null) {
            cache.set(redisKey, JSON.toJSONString(payChannelParamDTOS));
        }
    }

    /**
     * 根据应用和服务类型查询支付渠道参数列表     结果可能是多个(支付宝param 微信param)
     * @param appId           应用id
     * @param platformChannel 服务类型code
     * @return
     */
    @Override
    public List<PayChannelParamDTO> queryPayChannelParamByAppAndPlatform(String appId, String platformChannel) throws BusinessException {
        // 先从redis查询，如果有则返回
        // 从缓存查询
        // 1.key的构建 如：HM_PAY_PARAM:b910da455bc84514b324656e1088320b:huimin_c2b
        String redisKey = RedisUtil.keyBuilder(appId, platformChannel);
        // 是否有缓存
        Boolean exists = cache.exists(redisKey);
        if (exists) {
            // 从redis获取支付渠道参数列表（json串）
            String PayChannelParamDTO_String = cache.get(redisKey);
            System.out.println(PayChannelParamDTO_String);
            // 将json串转成 List<PayChannelParamDTO>
            List<PayChannelParamDTO> payChannelParamDTOS = JSON.parseArray(PayChannelParamDTO_String, PayChannelParamDTO.class);
            return payChannelParamDTOS;
        }

        // 缓存中没有 则从数据库查询  根据应用和服务类型找到它们绑定id
        Long appPlatformChannelId = selectIdByAppPlatformChannel(appId, platformChannel);
        if (appPlatformChannelId == null) {
            return null;
        }
        // 应用和服务类型绑定id查询支付渠道参数记录
        List<PayChannelParam> payChannelParams = payChannelParamMapper.selectList(
                new LambdaQueryWrapper<PayChannelParam>().eq(PayChannelParam::getAppPlatformChannelId, appPlatformChannelId));
        List<PayChannelParamDTO> payChannelParamDTOS = PayChannelParamConvert.INSTANCE.listentity2listdto(payChannelParams);
        // 保存到redis
        // updateCache(appId,platformChannel);
        cache.set(redisKey, JSON.toJSONString(payChannelParamDTOS));
        return payChannelParamDTOS;
    }

    /**
     * 获取指定应用指定服务类型下所包含的某个原始支付参数
     * @param appId
     * @param platformChannel
     * @param payChannel
     * @return
     * @throws BusinessException
     */
    @Override
    public PayChannelParamDTO queryParamByAppPlatformAndPayChannel(String appId, String platformChannel, String payChannel) throws BusinessException {
        List<PayChannelParamDTO> payChannelParamDTOS = queryPayChannelParamByAppAndPlatform(appId, platformChannel);
        for (PayChannelParamDTO payChannelParamDTO : payChannelParamDTOS) {
            if (payChannelParamDTO.getPayChannel().equals(payChannel)) {
                return payChannelParamDTO;
            }
        }
        return null;
    }


    /**
     * 根据应用id 、服务类型 code 查询应用与服务类型的绑定id
     * @param appId
     * @param platformChannelCode
     * @return
     */
    private Long selectIdByAppPlatformChannel(String appId, String platformChannelCode) {
        AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(
                new LambdaQueryWrapper<AppPlatformChannel>()
                        .eq(AppPlatformChannel::getAppId, appId)
                        .eq(AppPlatformChannel::getPlatformChannel, platformChannelCode));

        System.out.println("--------------------------");
        System.out.println(appId);
        System.out.println(platformChannelCode);
        System.out.println(appPlatformChannel);

        if (appPlatformChannel != null) {
            return appPlatformChannel.getId();                        // 应用与服务类型的绑定id
        }
        return null;
    }

}
